<template>
  <u-dialog :title="$t('option.title')"
            type="none"
            v-model="display_"
            v-if="editOptions">
    <q-btn class="full-width" color="primary" :label="$t('option.reset.label')" @click="onResetEvent"/>
    <q-tabs v-model="optionTab" class="q-mt-md">
      <q-tab name="live" :label="$t('option.live.title')"/>
      <q-tab name="effect" :label="$t('option.effect.title')"/>
      <q-tab name="locale" :label="$t('option.locale.title')"/>
    </q-tabs>
    <q-tab-panels v-model="optionTab">
      <q-tab-panel name="live">
        <div class="row q-col-gutter-md">
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.live.speed') }}</div>
            <div class="col-xs-12">
              <button-number :label="`${ editOptions.gameConfig.speed.toFixed(1) }`"
                             :value="Math.round(editOptions.gameConfig.speed * 10) / 10"
                             @change="function (value) { editOptions.gameConfig.speed = value }"
                             :minValue="1.0" :maxValue="11.0"
                             :smallStep="0.1" :bigStep="0.5" :cycle="true"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.live.noteScale') }}</div>
            <div class="col-xs-12">
              <button-number :label="`${Math.round(editOptions.gameConfig.noteScale * 100)}%`"
                             :value="Math.round(editOptions.gameConfig.noteScale * 100) / 100"
                             @change="function (value) { editOptions.gameConfig.noteScale = value }"
                             :minValue="0.1" :maxValue="2.0"
                             :smallStep="0.1" type="small" :cycle="true"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.live.judgeOffset') }}</div>
            <div class="col-xs-12">
              <button-number :label="`${Math.round(editOptions.gameConfig.judgeOffset)}`"
                             :value="Math.round(editOptions.gameConfig.judgeOffset)"
                             @change="function (value) { editOptions.gameConfig.judgeOffset = value }"
                             :minValue="-480" :maxValue="480"
                             :smallStep="1" :bigStep="5" type="smallBig" :cycle="true"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.live.visualOffset') }}</div>
            <div class="col-xs-12">
              <button-number :label="`${Math.round(editOptions.gameConfig.visualOffset)}`"
                             :value="Math.round(editOptions.gameConfig.visualOffset)"
                             @change="function (value) { editOptions.gameConfig.visualOffset = value }"
                             :minValue="-480" :maxValue="480"
                             :smallStep="1" :bigStep="5" type="smallBig" :cycle="true"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.live.barOpacity') }}</div>
            <div class="col-xs-12">
              <button-number :label="`${Math.round(editOptions.gameConfig.barOpacity * 100)}%`"
                             :value="Math.round(editOptions.gameConfig.barOpacity * 100) / 100"
                             @change="function (value) { editOptions.gameConfig.barOpacity = value }"
                             :minValue="0.1" :maxValue="1.0"
                             :smallStep="0.1" type="small" :cycle="true"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.live.backgroundDim') }}</div>
            <div class="col-xs-12">
              <button-number :label="`${Math.round(editOptions.gameConfig.backgroundDim * 100)}%`"
                             :value="Math.round(editOptions.gameConfig.backgroundDim * 100) / 100"
                             @change="function (value) { editOptions.gameConfig.backgroundDim = value }"
                             :minValue="0.1" :maxValue="1.0"
                             :smallStep="0.1" type="small" :cycle="true"/>
            </div>
          </div>
          <div class="col-xs-12 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.live.resolution') }}</div>
            <div class="col-xs-12">
              <q-slider v-model="editOptions.gameConfig.resolution" :min="1" :max="2" :step="1" label/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">
              <q-toggle :label="$t('option.live.showSimLine')" v-model="editOptions.gameConfig.showSimLine"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">
              <q-toggle :label="$t('option.live.beatNote')" v-model="editOptions.gameConfig.beatNote"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">
              <q-toggle :label="$t('option.live.mirror')" v-model="editOptions.gameConfig.mirror"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">
              <q-toggle :label="$t('option.live.laneEffect')" v-model="editOptions.gameConfig.laneEffect"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">
              <q-toggle :label="$t('option.live.autoFullscreen')" v-model="editOptions.autoFullscreen"/>
            </div>
          </div>
          <div class="col-xs-12 col-md-6 row q-col-gutter-sm">
            <div class="col-xs-12">
              <q-toggle :label="$t('option.live.upperHidden')" v-model="editOptions.upperHidden"/>
            </div>
          </div>
          <div class="col-xs-12 row q-col-gutter-sm" v-if="editOptions.upperHidden">
            <div class="col-xs-12">
              <image-selector v-model="editOptions.upperHiddenImg"
                              :label="$t('public.selectImage')"
                              :reset="$t('public.reset')"
                              :title="$t('option.live.upperHiddenImage')"/>
            </div>
          </div>
        </div>
      </q-tab-panel>
      <q-tab-panel name="effect">
        <div class="row q-col-gutter-md">
          <div class="col-xs-12 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.effect.skin') }}</div>
            <div class="col-xs-12">
              <q-select v-model="editOptions.skin"
                        :options="skinList()"
                        emit-value
                        map-options/>
            </div>
          </div>
          <div class="col-xs-12 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.effect.sound') }}</div>
            <div class="col-xs-12">
              <q-select v-model="editOptions.sound"
                        :options="soundList()"
                        emit-value
                        map-options/>
            </div>
            <div class="col-xs-12 q-gutter-md text-center">
              <q-btn icon="play_arrow" :label="$t('option.effect.perfect')"
                     @click="playAudio(`statics/player/skins/${editOptions.sound === 'skin' ? editOptions.skin : editOptions.sound}/perfect.mp3`)"/>
              <q-btn icon="play_arrow" :label="$t('option.effect.flick')"
                     @click="playAudio(`statics/player/skins/${editOptions.sound === 'skin' ? editOptions.skin : editOptions.sound}/flick.mp3`)"/>
            </div>
          </div>
          <div class="col-xs-12 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.effect.bg') }}</div>
            <div class="col-xs-12">
              <q-select v-model="editOptions.bg"
                        :options="bgList()"
                        emit-value
                        map-options/>
            </div>
            <div class="col-xs-12" v-if="editOptions.bg === 'custom'">
              <image-selector v-model="editOptions.customBg"
                              :label="$t('public.selectImage')"
                              :reset="$t('public.reset')" :title="$t('option.effect.customBg')"/>
            </div>
          </div>
          <div class="col-xs-12 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.effect.effectVolume') }}</div>
            <div class="col-xs-12">
              <q-slider v-model="editOptions.gameConfig.effectVolume" :min="0" :max="1" :step="0.01"
                        label
                        :label-value="`${Math.floor(editOptions.gameConfig.effectVolume * 100)}%`"/>
            </div>
          </div>
        </div>
      </q-tab-panel>
      <q-tab-panel name="locale">
        <div class="row q-col-gutter-md">
          <div class="col-xs-12 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.locale.language') }}</div>
            <div class="col-xs-12">
              <q-select v-model="editOptions.language"
                        :options="languageList()"
                        emit-value
                        map-options/>
            </div>
          </div>
          <div class="col-xs-12 row q-col-gutter-sm">
            <div class="col-xs-12">{{ $t('option.locale.proxy') }}</div>
            <div class="col-xs-12">
              <q-select v-model="editOptions.baseUrl"
                        :options="proxyList()"
                        emit-value
                        map-options
                        :disable="testing"/>
            </div>
            <div class="col-xs-12 text-center">
              <q-btn class="full-width" :label="'测试是否畅通'"
                     @click="testNetwork"
                     :loading="testing"
                     :disable="testing">
                <template v-slot:loading>
                  <div class="row q-col-gutter-md">
                    <q-spinner-cube size="lg" class="col-auto"/>
                    <div class="col-auto">{{ speed }}</div>
                  </div>
                </template>
              </q-btn>
            </div>
            <div v-if="result != ''" class="col-xs-12 text-center text-caption text-grey">{{ result }}</div>
          </div>
        </div>
      </q-tab-panel>
    </q-tab-panels>
    <q-inner-loading class="relative-position" :showing="isFileLoading">
      <q-spinner-grid size="48px" color="primary"/>
    </q-inner-loading>
  </u-dialog>
</template>

<script>
  import UDialog from "src/components/public/UDialog";
  import ButtonNumber from 'src/components/player/ButtonNumber.vue'
  import * as optionHelper from 'src/lib/playerOptionUtil.js'
  import notify from "src/lib/notifyUtil";
  import ImageSelector from "../../components/player/ImageSelector";
  import setProxyUrl from "../../lib/proxyUtil";

  export default {
    name: "Options",
    components: {ImageSelector, UDialog, ButtonNumber},
    props: {
      display: {
        type: Boolean,
        default: false
      }
    },
    data: function () {
      return {
        display_: this.display,
        editOptions: optionHelper.readPlayerOptions(),
        dialogDisplay: false,
        optionTab: 'live',
        isFileLoading: false,
        testing: false,
        lastProgress: 0,
        lastTime: new Date().getTime(),
        downloadSpeed: 0,
        speed: '0KB/s',
        maxSpeed: 0,
        startTime: 0,
        totalSize: 0,
        result: ''
      }
    },
    watch: {
      display(n) {
        this.display_ = n;
        if (n) this.editOptions = optionHelper.readPlayerOptions();
        else optionHelper.savePlayerOptions(this.editOptions);
      },
      display_(n) {
        this.$emit('onDisplayChange', n);
      },
      'editOptions.language': {
        handler: function () {
          this.$i18n.locale = this.editOptions.language;
        }
      },
      speed(v) {
        console.log(v);
      }
    },
    model: {
      prop: 'display',
      event: 'onDisplayChange'
    },
    methods: {
      languageList() {
        let list = [];
        optionHelper.languageList.forEach(item => {
          list.push({
            label: this.$t(`data.language.${item}`),
            value: item
          })
        });
        return list;
      },
      skinList() {
        let list = [];
        optionHelper.skinList.forEach(item => {
          list.push({
            label: this.$t(`data.skin.${item}`),
            value: item
          })
        });
        return list;
      },
      soundList() {
        let list = [];
        optionHelper.soundList.forEach(item => {
          list.push({
            label: this.$t(`data.skin.${item}`),
            value: item
          })
        });
        return list;
      },
      bgList() {
        let list = [];
        optionHelper.backgroundList.forEach(item => {
          list.push({
            label: this.$t(`data.skin.${item}`),
            value: item
          })
        });
        return list;
      },
      proxyList() {
        let list = [];
        optionHelper.proxyList.forEach(item => {
          list.push({
            label: this.$t(`data.proxy.${item}`),
            value: item
          })
        });
        return list;
      },
      async onFileChangeEvent(event) {
        this.isFileLoading = true;
        let that = this;
        try {
          const files = event.target.files;
          const reader = new FileReader();
          await reader.readAsDataURL(files[0]);
          reader.onload = function (e) {
            that.editOptions.customBg = this.result;
          }
        } catch (e) {
          notify(this.$t('public.error'), this.$t('ERR_LOAD_FILE_ERROR'), 'clear');
        }
        this.isFileLoading = false
      },
      playAudio(src) {
        let audio = new Audio();
        audio.src = src;
        audio.play();
      },
      onResetEvent() {
        this.editOptions = optionHelper.resetPlayerOptions();
        notify(this.$t('option.OPTION_RESET'), null, 'check');
      },
      async testNetwork() {
        this.testing = true;
        this.downloadSpeed = 0;
        this.maxSpeed = 0;
        this.totalSize = 0;
        this.startTime = 0;
        this.lastTime = new Date().getTime();
        this.speed = '0KB/s';
        this.lastProgress = 0;
        this.result = '';
        try {
          await this.$axios({
            method: 'get',
            url: setProxyUrl(`https://bestdori.com/api/upload/8/post_image/s4a3ofamjxlkdzbqnkjk?_=${new Date().getTime()}`, this.editOptions.baseUrl),
            responseType: 'arraybuffer',
            onDownloadProgress: this.onDownloadProgress
          });
          let totalTime = new Date().getTime() - this.startTime;
          let avgSpeed = (this.totalSize / (totalTime / 1000));
          if(avgSpeed > this.maxSpeed) this.maxSpeed = avgSpeed;
          let max = `${(this.maxSpeed > 1024 * 1024) ?
            `${Math.round(this.maxSpeed / 1024 / 1024 * 100) / 100}MB/s` :
            `${Math.round(this.maxSpeed / 1024 * 100) / 100}KB/s`}`;
          let avg = `${(avgSpeed > 1024 * 1024) ?
            `${Math.round(avgSpeed / 1024 / 1024 * 100) / 100}MB/s` :
            `${Math.round(avgSpeed / 1024 * 100) / 100}KB/s`}`;
          this.result = this.$t('option.locale.testDone', { max, avg });
        } catch (e) {
          notify(this.$t('public.error'), this.$t('Network Error'), 'clear');
        } finally {
          this.testing = false;
        }
      },
      onDownloadProgress(progress) {
        const currentTime = new Date().getTime();
        if (this.startTime === 0) this.startTime = currentTime;
        if (!this.lastTime || currentTime - this.lastTime > 1000) {
          this.downloadSpeed = (progress.loaded - this.lastProgress) / ((currentTime - this.lastTime) / 1000);
          this.lastProgress = progress.loaded;
          this.lastTime = currentTime;
        }
        this.totalSize = progress.loaded;
        this.speed = `${(this.downloadSpeed > 1024 * 1024) ?
          `${Math.round(this.downloadSpeed / 1024 / 1024 * 100) / 100}MB/s` :
          `${Math.round(this.downloadSpeed / 1024 * 100) / 100}KB/s`}`;
        if(this.downloadSpeed > this.maxSpeed) this.maxSpeed = this.downloadSpeed;
      }
    }
  }
</script>

<style scoped>

</style>
